#include "RecvCMD.h"

#define MEMREAD1(name)	MEMREAD(name, Recv)

//************************************
// Method:    	tRecvCMD				接收上位下发的命令字线程
// Programmer:  lww
// Time:		2019/1/20
// Returns:   	void *
// Parameter: 	void * arg
//************************************
void *tRecvCMD(void* arg)
{
#define PACK_MAXNUM	10240 //lijun0729更改 由3072改为10240，解决卡件总召唤确认后上位崩溃
#define ORDER_SIZE	3
#define WRONG_DEAL	{\
	printf("Recv CMD wrong!\r\n");\
	continue;\
}

	int sock, sock_accept;
	char Recv[PACK_MAXNUM] = { 0 };
	char Order[4] = { 0 };
	int Data_Len = 0;
	int tmp_int = 0;
	int MSG_Len = 0;

	printf("the Kernel_%s is %d\r\n", "tRecvCMD_ID", syscall(SYS_gettid));			//< duan20200610
	//< 初始化TCP服务器端设置
	if (false == TCP_Sever_Init(&sock, CMD_PORT, 0, nullptr))
		return 0;
	while (1)
	{
		//< 等待被连接
		if (false == TCP_Sever_Accept(&sock, &sock_accept, 5))
			continue;

		//< 接收前四字节的数据，前四字节存储了数据包长度
		Data_Len = 0;
		memset(Recv, 0, sizeof(Recv));
		if (-1 == TCP_Recv(&sock_accept, Recv, sizeof(Data_Len), 10000))
			WRONG_DEAL;
		memcpy(&Data_Len, Recv, sizeof(Data_Len));
		printf("%s",Recv);

		//< 读取命令字
		memset(Order, 0, sizeof(Order));
		if (-1 == TCP_Recv(&sock_accept, Order, ORDER_SIZE, 10000))
			WRONG_DEAL;
		printf("%s", Order);
		//< 读站号，进行核对
		memset(Recv, 0, sizeof(Recv));
		if (-1 == TCP_Recv(&sock_accept, Recv, sizeof(tmp_int), 10000))
			WRONG_DEAL;
		memcpy(&tmp_int, Recv, sizeof(tmp_int));
		if (tmp_int != Station_ID - 1)
			WRONG_DEAL;

		//< 读剩余信息（要少读前面读过的那些字节）
		MSG_Len = (int)(Data_Len - sizeof(Data_Len) - ORDER_SIZE - sizeof(tmp_int));
		memset(Recv, 0, sizeof(Recv));
		if (-1 == TCP_Recv(&sock_accept, Recv, MSG_Len, 10000))
			WRONG_DEAL;

		printf("%s", Recv);
		//< 断开连接
		close(sock_accept);

		//< 指令处理
		CMD_Deal(Order, Recv, MSG_Len);
		/*BCIO_flag = true;
		BCIO_begin = RealTime_Get();*/
	}
	close(sock);

#undef WRONG_DEAL
#undef ORDER_SIZE
#undef PACK_MAXNUM
}


//************************************
// Method:    	CMD_Deal				下发命令处理
// Programmer:  lww
// Time:		2019/2/16
// Returns:   	void
// Parameter: 	char * Order			命令字
// Parameter: 	char * Recv				报文
// Parameter: 	int Data_Len			数据区长度
//************************************
void CMD_Deal(char* Order, char* Recv, int Data_Len)
{
#define COMPARE(var)	!strcmp(Order, #var)

	if (COMPARE(STR))										//< 启动目标站目标页在线调试
		STR(Recv);
	else if (COMPARE(STP))									//< 停止目标站目标页在线调试
		STP(Recv);
	else if (COMPARE(DAR))									//< 启动目标站数据库在线调试
		DAR(Recv);
	else if (COMPARE(DAP))									//< 停止目标站数据库在线调试
		DAP(Recv);
	else if (COMPARE(MSC))									//< SAMA模块强制命令
		MSC(Recv);
	else if (COMPARE(MSH))									//< SAMA模块保持命令
		MSH(Recv);
	else if (COMPARE(MSU))									//< 取消SAMA强制\取消SAMA保持命令
		MSU(Recv);
	else if (COMPARE(MSF))									//< 修改SAMA模块参数
		MSF(Recv, Data_Len);
	else if (COMPARE(FAO) || COMPARE(MDO) || COMPARE(MSP) || COMPARE(MAO) || COMPARE(HAO) || COMPARE(FSP) || COMPARE(MDS))	//< 模拟量直接输出||模拟量输出“增”、“减”||MAO命令按下后弹起发送的命令字
		Model_CMD(Order, Recv);
	else if (COMPARE(ACK))									//< 数据点报警确认命令
		ACK(Recv);
	else if (COMPARE(MDH))									//< 数据点保持命令
		MDH(Recv);
	else if (COMPARE(MDC))									//< 数据点强制命令
		MDC(Recv);
	else if (COMPARE(MDU))									//< 取消数据点强制\取消数据点保持命令
		MDU(Recv);
	else if (COMPARE(MDF))									//< 修改卡件数据通道属性参数命令
		MDF(Recv, Data_Len);
	else if (COMPARE(MCF))									//< 修改卡件可调参数结构体命令
		MCF(Recv, Data_Len);

#undef COMPARE
}

//************************************
// Method:    	STR							启动目标站目标页在线调试
// Programmer:  lww
// Time:		2019/2/16
// Returns:   	void
// Parameter: 	char * Recv					数据包头指针
//************************************
void STR(char* Recv)
{
	int _iLen = 0;
	int tmp_int;

	MEMREAD1(tmp_int);
	if (tmp_int <= 0)
		printf("Debug page send wrong!\r\n");
	else
	{
		SAMA_PageBCFlag[tmp_int - 1] = true;
		BCSamaPara_Set.Flg = true;
		BCSamaPara_Set.Count = 0;
		printf("Debug page %d \r\n", tmp_int);
	}
}

//************************************
// Method:    	STP							停止目标站目标页在线调试
// Programmer:  lww
// Time:		2019/2/16
// Returns:   	void
// Parameter: 	char * Recv					数据包头指针
//************************************
void STP(char* Recv) 
{
	int _iLen = 0;
	int tmp_int;

	MEMREAD1(tmp_int);
	if (tmp_int <= 0)
		printf("Cancel debug page wrong!\r\n");
	else
	{
		SAMA_PageBCFlag[tmp_int - 1] = false;
		BCSamaPara_Set.Flg = false;
		BCSamaPara_Set.Count = 0;
		printf("Stop debug page %d \r\n", tmp_int);
	}
}

//************************************
// Method:    	DAR							启动目标站数据库在线调试
// Programmer:  lww
// Time:		2019/2/16
// Returns:   	void
// Parameter: 	char * Recv					数据包头指针
//************************************
void DAR(char* Recv)
{
//	BCIODataFlg = true;
	printf("Begin broadcast sysdata IO information!\r\n");
}

//************************************
// Method:    	DAP							停止目标站数据库在线调试
// Programmer:  lww
// Time:		2019/2/16
// Returns:   	void
// Parameter: 	char * Recv					数据包头指针
//************************************
void DAP(char* Recv)
{
//	BCIODataFlg = false;
	printf("Stop broadcast sysdata IO information!\r\n");
}

//************************************
// Method:    	MSC							强制SAMA命令
// Programmer:  lww
// Time:		2019/2/16
// Returns:   	void
// Parameter: 	char * Recv					数据包头指针
//************************************
void MSC(char* Recv)
{
	int _iLen = 0;
	int Model_Type, Model_ID;

	MEMREAD1(Model_Type);
	MEMREAD1(Model_ID);
	int outType;	MEMREAD1(outType);		//< 0模拟量，1数字量
	int IOIndex;	MEMREAD1(IOIndex);		//< 强制模块第几个输出（不区分数字量和模拟量）

	if (LIST_OK == ForceSta(&Model_List[Model_Type_Map[Model_Type]], Model_ID, ((bool)outType), IOIndex - 1, Recv))
		printf("Force NO.%d model success\r\n", Model_ID);
	else
		printf("Force NO.%d model fail\r\n", Model_ID);
}

//************************************
// Method:    	MSH							保持SAMA命令
// Programmer:  lww
// Time:		2019/2/16
// Returns:   	void
// Parameter: 	char * Recv					数据包头指针
//************************************
void MSH(char* Recv)
{
	int _iLen = 0;
	int Model_Type, Model_ID;

	MEMREAD1(Model_Type);
	MEMREAD1(Model_ID);
	int outType;	MEMREAD1(outType);		//< 0模拟量，1数字量
	int IOIndex;	MEMREAD1(IOIndex);		//< 模块第几个引脚（不区分数字量和模拟量）

	if (LIST_OK == HoldSta(&Model_List[Model_Type_Map[Model_Type]], Model_ID, ((bool)outType), IOIndex - 1))
		printf("Hold NO.%d model success\r\n", Model_ID);
	else
		printf("Hold NO.%d model fail\r\n", Model_ID);
}

//************************************
// Method:    	MSU							取消SAMA强制\取消SAMA保持命令
// Programmer:  lww
// Time:		2019/2/16
// Returns:   	void
// Parameter: 	char * Recv					数据包头指针
//************************************
void MSU(char* Recv)
{
	int _iLen = 0;
	int Model_Type, Model_ID;

	MEMREAD1(Model_Type);
	MEMREAD1(Model_ID);
	int outType;	MEMREAD1(outType);		//< 0模拟量，1数字量
	int IOIndex;	MEMREAD1(IOIndex);		//< 模块第几个引脚（不区分数字量和模拟量）

	if (LIST_OK == NormalSta(&Model_List[Model_Type_Map[Model_Type]], Model_ID, ((bool)outType), IOIndex - 1))
		printf("Cancel force/hold NO.%d model success\r\n", Model_ID);
	else
		printf("Cancel force/hold NO.%d model fail\r\n", Model_ID);
}

//************************************
// Method:    	MSF							修改SAMA模块参数
// Programmer:  lww
// Time:		2019/2/16
// Returns:   	void
// Parameter: 	char * Recv					数据包头指针
// Parameter: 	int Data_Len				数据区长度
//************************************
void MSF(char* Recv, int Data_Len)
{
	int _iLen = 0;
	int Model_Type, Model_ID;

	MEMREAD1(Model_Type);
	MEMREAD1(Model_ID);
	if (LIST_OK == OnlineChgPar(&Model_List[Model_Type_Map[Model_Type]], Model_ID, Model_Type, Recv, (int)(Data_Len - sizeof(Model_Type) - sizeof(Model_ID))))
		printf("NO.%d model change para success\r\n", Model_ID);
	else
		printf("NO.%d model change para fail\r\n", Model_ID);
}

//************************************
// Method:    	Model_CMD					操作模块的相关命令字
// Programmer:  lww
// Time:		2019/2/16
// Returns:   	void
// Parameter: 	char * Order				命令字
// Parameter: 	char * Recv					数据包头指针
//************************************
void Model_CMD(char* Order, char* Recv)
{
	int _iLen = 0;
	int Model_Type, Model_ID;

	MEMREAD1(Model_Type);
	MEMREAD1(Model_ID);

	Model_Type = Model_Type_Map[Model_Type];

	if (LIST_OK == MODEL_CMD_DEAL(&Model_List[Model_Type], Model_ID, Recv, Order))				//< duan 0713修改
		printf("NO.%d model carry out %s commend success\r\n", Model_ID, Order);
	else
		printf("NO.%d model carry out %s commend fail\r\n", Model_ID, Order);
}


//************************************
// Method:    	ACK							数据点报警确认命令
// Programmer:  lww
// Time:		2019/2/23
// Returns:   	void
// Parameter: 	char * Recv					数据包头指针
//************************************
void ACK(char* Recv)
{
	int i;
	int _iLen = 0;
	int AckNum;
	short type;
	unsigned int ChannelID;
	Channel_type_e result;
	void* Channel_pt = NULL;

	MEMREAD1(AckNum);
	for (i = 0; i < AckNum; i++)
	{
		MEMREAD1(type);
		MEMREAD1(ChannelID);
		result = Channel_Find(ChannelID, &Channel_pt);
		if (result != NODEFINE)
		{
			if (result == AO_CHA || result == AI_CHA)
				AV_Write((AVChannel_t*)Channel_pt, 0, ALARM_SURE);
			else if (result == DO_CHA || result == DI_CHA)
				DV_Write((DVChannel_t*)Channel_pt, false, ALARM_SURE);
			printf("NO.%d channel alarm sured success\r\n", ChannelID);
		}
	}
}

//************************************
// Method:    	MDH							数据点保持命令
// Programmer:  lww
// Time:		2019/2/23
// Returns:   	void
// Parameter: 	char * Recv					数据包头指针
//************************************
void MDH(char* Recv)
{
	int _iLen = 0;
	unsigned int ChannelID;
	Channel_type_e result;
	void* Channel_pt = NULL;

	MEMREAD1(ChannelID);

	result = Channel_Find(ChannelID, &Channel_pt);
	if (result != NODEFINE)
	{
		if (result == AO_CHA || result == AI_CHA)
			AV_Write((AVChannel_t*)Channel_pt, 0, TURN_HOLD);
		else if (result == DO_CHA || result == DI_CHA)
			DV_Write((DVChannel_t*)Channel_pt, false, TURN_HOLD);
		printf("NO.%d channel change to hold status\r\n", ChannelID);
	}
}

//************************************
// Method:    	MDC							数据点强制命令
// Programmer:  lww
// Time:		2019/2/23
// Returns:   	void
// Parameter: 	char * Recv					数据包头指针
//************************************
void MDC(char* Recv)
{
	int _iLen = 0;
	unsigned int ChannelID;
	Channel_type_e result;
	void* Channel_pt = NULL;
	float tmp_float;
	bool tmp_bool;

	MEMREAD1(ChannelID);					//< duan0515 读取点ID（通道ID）

	result = Channel_Find(ChannelID, &Channel_pt);		//< duan0515 Channel_pt：通道指针 result：通道类型
	if (result != NODEFINE)
	{
		if (result == AO_CHA || result == AI_CHA)
		{
			MEMREAD1(tmp_float);
			AV_Write((AVChannel_t*)Channel_pt, tmp_float, TURN_FORCE);
		}
		else if (result == DO_CHA || result == DI_CHA)
		{
			MEMREAD1(tmp_bool);
			DV_Write((DVChannel_t*)Channel_pt, tmp_bool, TURN_FORCE);
		}
		printf("NO.%d channel force success\r\n", ChannelID);
		
	}
}

//************************************
// Method:    	MDU							取消数据点强制\取消数据点保持命令
// Programmer:  lww
// Time:		2019/2/23
// Returns:   	void
// Parameter: 	char * Recv					数据包头指针
//************************************
void MDU(char* Recv)
{
	int _iLen = 0;
	unsigned int ChannelID;
	Channel_type_e result;
	void* Channel_pt = NULL;

	MEMREAD1(ChannelID);

	result = Channel_Find(ChannelID, &Channel_pt);
	if (result != NODEFINE)
	{
		if (result == AO_CHA || result == AI_CHA)
		{
			AVChannel_t *Base_av = (AVChannel_t*)Channel_pt; //< lijun0811 应明华要求将取消强制\取消保持 后的写入值由0改为当前值
			AV_Write((AVChannel_t*)Channel_pt, Base_av->Sta_Property.CurOut_Value, TURN_NORMAL);
		}
		else if (result == DO_CHA || result == DI_CHA)
		{
			DVChannel_t *Base_dv = (DVChannel_t*)Channel_pt; //< lijun0811 应明华要求将取消强制\取消保持 后的写入值由0改为当前值
			DV_Write((DVChannel_t*)Channel_pt, Base_dv->Sta_Property.CurOut_Value, TURN_NORMAL);
		}
		printf("NO.%d channel cancel force/hold\r\n", ChannelID);
	}
}

//************************************
// Method:    	MDF							修改卡件数据通道属性参数命令
// Programmer:  lww
// Time:		2019/2/23
// Returns:   	void
// Parameter: 	char * Recv					数据包头指针
// Parameter: 	int Data_Len				数据区长度
//************************************
void MDF(char* Recv, int Data_Len)
{
	int _iLen = 0;
	unsigned int ChannelID;
	Channel_type_e result;
	void* Channel_pt = NULL;

	MEMREAD1(ChannelID);

	result = Channel_Find(ChannelID, &Channel_pt);
	if (result != NODEFINE)
	{
		//< 修改DATA文件
		if (Open2Write(DATA_FILE_PATH, ((DVAV_BASE_Property_t*)(Channel_pt))->File_Read_Offset, Recv, (Data_Len - (int)sizeof(ChannelID))) == false)
			printf("Change DATA file fail\r\n");

		ChangeChannelPar(Channel_pt, (void**)&Recv, result);
		printf("NO.%d channel change para success\r\n", ChannelID);
	}
}

//************************************
// Method:    	MCF							修改卡件可调参数结构体命令
// Programmer:  duan
// Time:		2019/2/23
// Returns:   	void
// Parameter: 	char * Recv					数据包头指针
// Parameter: 	int Data_Len				数据区长度
//************************************
void MCF(char* Recv, int Data_Len)
{
	int _iLen = 0;
	int i = 0;
	int Card_Type = 0;							//< 卡件类型
	unsigned int Card_Num = 0;					//< 卡件数目
	unsigned int Size_Par = 0;					//< 该类型卡件可调参数结构体字节数
	unsigned int Card_ID = 0;					//< 卡件ID

	Card_Base_t* base = NULL;

	MEMREAD1(Card_Type);
	MEMREAD1(Card_Num);
	MEMREAD1(Size_Par);

	for (i = 0; i < Card_Num; i++)
	{
		MEMREAD1(Card_ID);
		base = (Card_Base_t*)SearchId((List_Base_t*)(Card_List[Card_Type].ppData[0]), Card_ID);
		if (base != NULL)
		{
			//< 修改DATA文件
			if (Open2Write(DATA_FILE_PATH,base->Card_File_Read_Offset , Recv, Size_Par) == false)
				printf("Change DATA file fail\r\n");

			//< 修改卡件可调参数结构体
			_iLen += (((Card_List_Func_t*)(Card_List[Card_Type].List_Func))->ChangePar(base, (void**)&Recv));
		}
	}

	if (_iLen != Data_Len)
		printf("ERROR - the Len of MCF is Wrong\r\n");
	else
		printf("Card change para success\r\n");

}

#undef MEMREAD1